package com.shelly.singleton.type6;

/**
 * @author: Shelly
 * @create: 2023-01-10 16:57:09
 * @describe: 懒汉式- 双重检查
 *  * 1.优点：线程安全
 *  * 2.缺点：不能防止反射和序列化
 *
 * 类实例化步骤：
 * 1. 为 instance 分配内存空间
 * 2. 初始化 instance
 * 3. 将 instance 指向分配的内存地址
 * 由于 JVM 具有指令重排的特性，执行顺序有可能从1->2->3 变成 1->3->2
 * 指令重排在单线程环境下不会出现问题，但是在多线程环境下会导致一个线程获得还没有初始化的实例
 * 线程 T1 执行了 1 和 3，此时 T2 调用 getInstance() 后发现 instance 不为空，因此返回 instance，但此时instance 还未被初始化
 */
public class Singleton {
    // volatile:可以禁止 JVM 的指令重排，保证在多线程环境下也能正常运行
    private static volatile Singleton instance;// 不能加final，因为final类必须实例化
    // 私有化构造器
    private Singleton(){}

    // 提供外部调用方法
    public static Singleton getInstance(){
        if (instance == null){// 一重检查
            synchronized (Singleton.class){// 多线程加锁
                if (instance == null){// 二重检查
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    // 测试
    public static void main(String[] args) {
        Singleton a = Singleton.getInstance();
        Singleton b = Singleton.getInstance();
        System.out.println(a.equals(b));
        System.out.println(a);// 打印地址
        System.out.println(b);
    }
}
